// Copyright 2019 The rhyme_lph Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// A [author] rhyme_lph
// E [email]  rhymelph@gmail.com
// q [github] https://github.com/rhymelph

import 'dart:async';

import 'package:base_plugin/base_plugin.dart';
import 'package:finance_app/generated/l10n.dart';
import 'package:finance_app/src/http_service/http_login_service.dart';
import 'package:finance_app/src/router_gen/router_gen_providers.dart';
import 'package:flutter/material.dart';

class ForgotPasswordProvider extends BaseProvider {
  TextEditingController phoneController = TextEditingController();
  FocusNode phoneFocus = FocusNode();

  TextEditingController emailController = TextEditingController();
  FocusNode emailFocus = FocusNode();

  TextEditingController validateController = TextEditingController();
  FocusNode validateFocusNode = FocusNode();

  bool enableGetOTP = false;

  bool enableVerify = false;
  String number;

  bool hasValidateError = false;

  Timer timer;

  //默认的过期时间
  int defaultOTPExpireTime = 90;

  //当前过期时间
  int currentOTPExpireTimer = 0;

  String countryCode = "+65";

  bool hasPhoneError = false;
  bool hasEmailError = false;

  String currentType = S.current.email;

  @override
  void dispose() {
    super.dispose();
    timer?.cancel();
    phoneController.dispose();
    phoneFocus.dispose();
    emailController.dispose();
    emailFocus.dispose();
    validateController.dispose();
    validateFocusNode.dispose();
  }

  void onChangeType(String e) {
    if (currentType == e) return;
    currentType = e;
    _onUpdateGetOTPInput();
    update();
  }

  void onVerify() async {
    validateFocusNode.unfocus();
    String text = validateController.text;
    bool isSuccess = false;
    if (currentType == S.current.email) {
      await post(HttpLoginService.otpEmailCheckForget(number, text),
          loadingTip: S.current.loading, onSuccess: (result) {
        isSuccess = true;
      }, onError: (_, ____, __, ___) {
        hasValidateError = true;
        update();
      });
      if (isSuccess) {
        Routes.navigateTo(RouterGenProviders.setNewPasswordPage,
            replace: true,
            params: {
              'email': number,
              'otp': text,
            });
      }
    } else {
      await post(
          HttpLoginService.otpCheckForget(countryCode, getPhone(number), text),
          loadingTip: S.current.loading, onSuccess: (result) {
        isSuccess = true;
      }, onError: (_, ____, __, ___) {
        hasValidateError = true;
        update();
      });
      if (isSuccess) {
        Routes.navigateTo(RouterGenProviders.setNewPasswordPage,
            replace: true,
            params: {
              'phoneNumber': number,
              'otp': text,
              'countryCode': countryCode,
            });
      }
    }
  }

  void onGetOTP() async {
    bool isSuccess = false;

    if (currentType == S.current.email) {
      emailFocus.unfocus();
      String email = emailController.text;
      if (email.length < 8) {
        hasEmailError = true;
        update();
        return;
      }

      await post(HttpLoginService.resetOtpByEmail(email),
          autoHandler: AutoHandler.Toast,
          loadingTip: S.current.loading, onSuccess: (result) {
        isSuccess = true;
      });
      if (isSuccess) {
        _resetTimer();
        number = emailController.text;
        update();
      }
    } else {
      phoneFocus.unfocus();
      final phone = getPhone(phoneController.text);
      String phoneNumber = phoneController.text;
      if (phoneNumber.length < 8) {
        hasPhoneError = true;
        update();
        return;
      }

      await post(HttpLoginService.resetOtp(countryCode, phone),
          loadingTip: S.current.loading, onSuccess: (result) {
        isSuccess = true;
      });

      if (isSuccess) {
        _resetTimer();
        number = phoneController.text;
        update();
      }
    }
  }

  String getPhone(String phoneText) {
    String phoneNumber = phoneText.replaceAll(' ', '');
    return phoneNumber;
  }

  @override
  void initState() {
    super.initState();
    phoneController.addListener(_onUpdateGetOTPInput);
    emailController.addListener(_onUpdateGetOTPInput);
    validateController.addListener(_onUpdateValidateInput);
  }

  void _onUpdateValidateInput() {
    if (validateController.text.length > 0) {
      if (enableVerify == false) {
        enableVerify = true;
        update();
      }
    } else {
      if (enableVerify == true) {
        enableVerify = false;
        update();
      }
    }
  }

  void _onUpdateGetOTPInput() {
    if (currentType == S.current.email) {
      if (emailController.text.length > 0) {
        if (enableGetOTP == false) {
          enableGetOTP = true;
          update();
        }
      } else {
        if (enableGetOTP == true) {
          enableGetOTP = false;
          update();
        }
      }
    } else {
      if (phoneController.text.length > 0) {
        if (enableGetOTP == false) {
          enableGetOTP = true;
          update();
        }
      } else {
        if (enableGetOTP == true) {
          enableGetOTP = false;
          update();
        }
      }
    }
  }

  @override
  Future get dataFuture => null;

  void onNavRegister() {
    Routes.navigateTo(RouterGenProviders.registerPage);
  }

  void onResentOTP() async {
    if (currentOTPExpireTimer > 0) {
      showToast(S.current.please_waiting);
      return;
    }
    bool isSuccess = false;
    if (currentType == S.current.email) {
      await post(HttpLoginService.resetOtpByEmail(number),
          loadingTip: S.current.loading, onSuccess: (result) {
        isSuccess = true;
      });
    } else {
      final phone = getPhone(number);
      await post(HttpLoginService.resetOtp(countryCode, phone),
          loadingTip: S.current.loading, onSuccess: (result) {
        isSuccess = true;
      });
    }
    if (isSuccess) {
      hasValidateError = false;
      _resetTimer();
      update();
    }
  }

  void _resetTimer() {
    timer?.cancel();
    currentOTPExpireTimer = defaultOTPExpireTime;
    timer = Timer.periodic(Duration(seconds: 1), (timer) {
      if (currentOTPExpireTimer > 0) {
        currentOTPExpireTimer--;
        update();
      } else {
        update();
        timer?.cancel();
      }
    });
  }

  void onChangeCountryCode(value) {
    countryCode = value;
  }
}
